home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Sample Code / AppsToGo / Kibitz / Menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-24  |  13.7 KB  |  511 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        menu.c
  5. ** Written by:  Eric Soldan
  6. **
  7. ** Copyright © 1990-1992 Apple Computer, Inc.
  8. ** All rights reserved. */
  9.  
  10.  
  11.  
  12. /*****************************************************************************/
  13.  
  14.  
  15.  
  16. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  17. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  18. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  19.  
  20. #ifndef __DESK__
  21. #include <Desk.h>
  22. #endif
  23.  
  24. #ifndef __ERRORS__
  25. #include <Errors.h>
  26. #endif
  27.  
  28. #ifndef __MENUS__
  29. #include <Menus.h>
  30. #endif
  31.  
  32. #ifndef __STRING__
  33. #include <String.h>
  34. #endif
  35.  
  36. #ifndef __TEXTEDITCONTROL__
  37. #include <TextEditControl.h>
  38. #endif
  39.  
  40. #ifndef __TOOLUTILS__
  41. #include <ToolUtils.h>
  42. #endif
  43.  
  44. #ifndef __UTILITIES__
  45. #include <Utilities.h>
  46. #endif
  47.  
  48.  
  49.  
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. extern Boolean    gQuitApplication;
  55. extern Boolean    gHasAppleEvents;
  56. extern Boolean    gHasPPCToolbox;
  57. extern Boolean    gSendToSelf;
  58. extern short    gReplyMode;
  59.  
  60. short            gMenuMods;
  61.  
  62.  
  63.  
  64. /*****************************************************************************/
  65. /*****************************************************************************/
  66.  
  67.  
  68.  
  69. /* Enable and disable menus based on the current state.  The user can only
  70. ** select enabled menu items.  We set up all the menu items before calling
  71. ** MenuSelect or MenuKey, since these are the only times that a menu item can
  72. ** be selected.  Note that MenuSelect is also the only time the user will see
  73. ** menu items.  This approach to deciding what enable/ disable state a menu
  74. ** item has the advantage of concentrating all the decision-making in one
  75. ** routine, as opposed to being spread throughout the application.  Other
  76. ** application designs may take a different approach that is just as valid. */
  77.  
  78. #pragma segment Menu
  79. void    AdjustMenus(void)
  80. {
  81.     WindowPtr        window;
  82.     MenuHandle        menu;
  83.     short            numWindows, activeItem;
  84.     Boolean            maxWindows, menuEnabled, redrawMenuBar, winIsDirty, fileIsOpen;
  85.     TEHandle        teHndl;
  86.     Rect            rct;
  87.     FileRecHndl        frHndl;
  88.     static Boolean    editMenuEnabled   = true;
  89.     static Boolean    gameMenuEnabled   = true;
  90.  
  91.     redrawMenuBar = false;
  92.     window = FrontWindow();
  93.  
  94.     if (IsAppWindow(window)) frHndl = (FileRecHndl)GetWRefCon(window);
  95.  
  96.     menu = GetMenuHandle(mFile);
  97.  
  98.     EnableItem(menu, iNew);                /* Set these for the no-windows state. */
  99.     EnableItem(menu, iOpen);
  100.     EnableItem(menu, iMessage);
  101.     if (MaxBlock() < 0x10000L) {
  102.         if (CompactMem(0x10000L) < 0x10000L) {
  103.             DisableItem(menu, iNew);    /* Running low on RAM. */
  104.             DisableItem(menu, iOpen);
  105.         }
  106.     }
  107.  
  108.     DisableItem(menu, iClose);
  109.     DisableItem(menu, iSave);
  110.     DisableItem(menu, iSaveAs);
  111.     DisableItem(menu, iSaveBoardImage);
  112.     DisableItem(menu, iDuplicate);
  113.     DisableItem(menu, iRevert);
  114.     DisableItem(menu, iPageSetup);
  115.     DisableItem(menu, iPrint);
  116.         /* Quit is always hilited. */
  117.  
  118.  
  119.  
  120.     if (IsDAWindow(window)) {
  121.         DisableItem(menu, iNew);        /* DAs don't get to do a new. */
  122.         DisableItem(menu, iOpen);        /* DAs don't get to do an open. */
  123.         DisableItem(menu, iMessage);    /* DAs don't get to do a new. */
  124.         EnableItem(menu, iClose);        /* Let DAs do a close from the menu. */
  125.     }
  126.  
  127.     if (IsAppWindow(window)) {
  128.         numWindows = GetWindowCount(false, false, false);
  129.         maxWindows = (numWindows < kMaxNumWindows);
  130.         EnableOrDisableItem(menu, iNew, maxWindows);
  131.         EnableOrDisableItem(menu, iOpen, maxWindows);
  132.         EnableOrDisableItem(menu, iMessage, maxWindows);
  133.             /* Allow a new and open only if max number of files not reached. */
  134.  
  135.         winIsDirty = AppWindowDirty(window);
  136.         fileIsOpen = ((*frHndl)->fileState.fss.vRefNum != kInvalVRefNum);
  137.  
  138.         EnableItem(menu, iClose);
  139.         EnableOrDisableItem(menu, iSave, winIsDirty);
  140.         EnableItem(menu, iSaveAs);
  141.         if ((*frHndl)->doc.myColor != kMessageDoc) EnableItem(menu, iSaveBoardImage);
  142.         EnableItem(menu, iDuplicate);
  143.         EnableOrDisableItem(menu, iRevert, ((winIsDirty) && (fileIsOpen)));
  144.  
  145.         EnableItem(menu, iPageSetup);
  146.         EnableItem(menu, iPrint);
  147.     }
  148.  
  149.  
  150.  
  151.     menu = GetMenuHandle(mEdit);
  152.     DisableItem(menu, iSelectAll);
  153.     if (IsDAWindow(window)) {        /* A desk accessory may need edit menu. */
  154.         menuEnabled = true;
  155.         EnableItem(menu, iUndo);
  156.         EnableItem(menu, iCut);
  157.         EnableItem(menu, iCopy);
  158.         EnableItem(menu, iPaste);
  159.         EnableItem(menu, iClear);
  160.     } else {
  161.         menuEnabled = false;
  162.         if (window) {
  163.             CTEEditMenu(&menuEnabled, mEdit, iUndo, iCut);
  164.             if (CTETargetInfo(&teHndl, &rct) == window) {
  165.                 if ((*teHndl)->teLength) {
  166.                     EnableItem(menu, iSelectAll);
  167.                     menuEnabled = true;
  168.                 }
  169.             }
  170.         }
  171.     }
  172.     if (editMenuEnabled != menuEnabled) {
  173.         redrawMenuBar = true;
  174.         editMenuEnabled = menuEnabled;
  175.         if (editMenuEnabled) EnableItem(menu, 0);
  176.         else                 DisableItem(menu, 0);
  177.     }
  178.  
  179.  
  180.  
  181.     menu = GetMenuHandle(mGame);                /* Start by disabling everything. */
  182.     menuEnabled = false;
  183.     DisableItem(menu, iConfigureGame);
  184.     DisableItem(menu, iInvertBoard);
  185.     DisableItem(menu, iArrangeBoard);
  186.     DisableItem(menu, iPlayOnePlayer);
  187.     DisableItem(menu, iPlayTwoPlayer);
  188.     DisableItem(menu, iFindTwoPlayer);
  189.     DisableItem(menu, iGoToMove);
  190.     DisableItem(menu, iAlgOut);
  191.     DisableItem(menu, iAlgIn);
  192.  
  193.     CheckItem(menu, iArrangeBoard, false);
  194.     CheckItem(menu, iPlayOnePlayer, false);
  195.     CheckItem(menu, iPlayTwoPlayer, false);
  196.     CheckItem(menu, iFindTwoPlayer, false);
  197.  
  198.     if (IsAppWindow(window)) {
  199.  
  200.         if (!(*frHndl)->fileState.readOnly) {
  201.  
  202.             if ((*frHndl)->doc.myColor != kMessageDoc) {
  203.  
  204.                 menuEnabled = true;
  205.  
  206.                 if (!(*frHndl)->doc.arrangeBoard) {
  207.                     EnableItem(menu, iConfigureGame);
  208.                     EnableItem(menu, iArrangeBoard);
  209.                 }
  210.                 EnableItem(menu, iInvertBoard);
  211.                 EnableItem(menu, iPlayOnePlayer);
  212.                 if (gHasAppleEvents) {                /* Now the 7.0 goodie... */
  213.                     EnableItem(menu, iPlayTwoPlayer);
  214.                     EnableItem(menu, iFindTwoPlayer);
  215.                 }
  216.  
  217.                 if ((*frHndl)->doc.numGameMoves)
  218.                     EnableItem(menu, iGoToMove);
  219.  
  220.                 if ((*frHndl)->doc.gameIndex < (*frHndl)->doc.numGameMoves)
  221.                     EnableItem(menu, iAlgOut);
  222.  
  223.                 teHndl = (*frHndl)->doc.message[kMessageOut];
  224.                 if ((*teHndl)->selStart != (*teHndl)->selEnd)
  225.                     EnableItem(menu, iAlgIn);
  226.  
  227.                 activeItem = iPlayOnePlayer + (*frHndl)->doc.twoPlayer;
  228.                 if ((*frHndl)->doc.arrangeBoard) activeItem = iArrangeBoard;
  229.                 DisableItem(menu, activeItem);
  230.                 if (activeItem == iPlayTwoPlayer) DisableItem(menu, iFindTwoPlayer);
  231.                 CheckItem(menu, activeItem, true);
  232.             }
  233.         }
  234.     }
  235.     if (gameMenuEnabled != menuEnabled) {
  236.         redrawMenuBar = true;
  237.         gameMenuEnabled = menuEnabled;
  238.         if (gameMenuEnabled)
  239.              EnableItem(menu, 0);
  240.         else DisableItem(menu, 0);
  241.     }
  242.  
  243.  
  244.  
  245.     if (redrawMenuBar) DrawMenuBar();
  246. }
  247.  
  248.  
  249.  
  250. /*****************************************************************************/
  251.  
  252.  
  253.  
  254. /* This function either enables or disables a menu item. */
  255.  
  256. #pragma segment Menu
  257. void    EnableOrDisableItem(MenuHandle menu, short item, Boolean enable)
  258. {
  259.     if (enable) EnableItem(menu, item);
  260.     else        DisableItem(menu, item);
  261. }
  262.  
  263.  
  264.  
  265. /*****************************************************************************/
  266.  
  267.  
  268.  
  269. /* This is called when an item is chosen from the menu bar (after calling
  270. ** MenuSelect or MenuKey).  It performs the right operation for each command.
  271. ** It is good to have both the result of MenuSelect and MenuKey go to one
  272. ** routine like this to keep everything organized. */
  273.  
  274. #pragma segment Menu
  275. void    DoMenuCommand(long menuResult, EventRecord *event)
  276. {
  277.     short        menuID;            /* The resource ID of the selected menu. */
  278.     short        menuItem;        /* The item number of the selected menu. */
  279.     Str255        daName;
  280.     short        daRefNum, arrangeBoard;
  281.     FileRecHndl    frHndl, newFrHndl;
  282.     OSErr        err;
  283.     WindowPtr    window, oldPort;
  284.     short        itemHit;
  285.     DialogPtr    dlg;
  286.     StringPtr    nbpType;
  287.     TEHandle    teHndl;
  288.     Rect        rct;
  289.  
  290.     gMenuMods = event->modifiers;
  291.  
  292.     window = FrontWindow();
  293.     if (window)
  294.         frHndl = (FileRecHndl)GetWRefCon(window);
  295.             /* frHndl is valid only if it is one of our windows. */
  296.  
  297.     menuID = HiWord(menuResult);    /* Use macros for efficiency to get */
  298.     menuItem = LoWord(menuResult);    /* menu item number and menu number. */
  299.  
  300.     switch (menuID) {
  301.  
  302.         case mApple:
  303.             switch (menuItem) {
  304.                 case iAbout:    /* Bring up alert for About. */
  305.                     Alert(rAboutAlert, gAlertFilterUPP);
  306.                     break;
  307.                 default:        /* All non-About items in this menu are DAs. */
  308.                     GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
  309.                     daRefNum = OpenDeskAcc(daName);
  310.                     break;
  311.             }
  312.             break;
  313.  
  314.         case mFile:
  315.             switch (menuItem) {
  316.                 case iNew:
  317.                     err = AppNewDocument(&frHndl, ksOrigName);
  318.                     if (!err) {
  319.                         (*frHndl)->doc.compMovesBlack = true;
  320.                         err = AppNewWindow(frHndl, nil, (WindowPtr)-1);
  321.                         if (err)
  322.                             AppDisposeDocument(frHndl);
  323.                     }
  324.                     if (err) Alert(rErrorAlert, gAlertFilterUPP);
  325.                     break;
  326.                 case iOpen:
  327.                     err = AppOpenDocument(&frHndl, nil, fsRdWrPerm);
  328.                     if (!err) {
  329.                         err = AppNewWindow(frHndl, nil, (WindowPtr)-1);
  330.                         if (err)
  331.                             AppDisposeDocument(frHndl);
  332.                         else
  333.                             AppAutoLaunch(frHndl);
  334.                     }
  335.                     if ((err) && (err != userCanceledErr))
  336.                         Alert(rErrorAlert, gAlertFilterUPP);
  337.                     break;
  338.                 case iMessage:
  339.                     err = AppNewDocument(&frHndl, ksMssgName);
  340.                     if (!err) {
  341.                         err = AppNewWindow(frHndl, nil, (WindowPtr)-1);
  342.                         if (err)
  343.                             AppDisposeDocument(frHndl);
  344.                     }
  345.                     if (err) Alert(rErrorAlert, gAlertFilterUPP);
  346.                     break;
  347.                 case iClose:
  348.                     CloseOneWindow(window, iClose);
  349.                     break;
  350.                 case iSave:
  351.                     err = AppSaveDocument(frHndl, window, iSave);
  352.                     if ((err) && (err != userCanceledErr))
  353.                         Alert(rErrorAlert, gAlertFilterUPP);
  354.                     break;
  355.                 case iSaveAs:
  356.                     err = AppSaveDocument(frHndl, window, iSaveAs);
  357.                     if ((err) && (err != userCanceledErr))
  358.                         Alert(rErrorAlert, gAlertFilterUPP);
  359.                     break;
  360.                 case iSaveBoardImage:
  361.                     err = SaveBoardImage(frHndl);
  362.                     if ((err) && (err != userCanceledErr))
  363.                         Alert(rErrorAlert, gAlertFilterUPP);
  364.                     break;
  365.                 case iDuplicate:
  366.                     err = AppDuplicateDocument(frHndl, &newFrHndl);
  367.                     if (!err) {
  368.                         err = AppNewWindow(newFrHndl, nil, (WindowPtr)-1);
  369.                         if (err)
  370.                             AppDisposeDocument(newFrHndl);
  371.                     }
  372.                     if (err) Alert(rErrorAlert, gAlertFilterUPP);
  373.                     break;
  374.                 case iRevert:
  375.                     DoSetCursor(&qd.arrow);
  376.                     dlg = GetCenteredDialog(rRevertWarning, nil, FrontWindow(), (WindowPtr)-1L);
  377.                     if (dlg) {
  378.                         OutlineDialogItem(dlg, 1);
  379.                         ModalDialog(gKeyEquivFilterUPP, &itemHit);
  380.                         DisposeDialog(dlg);
  381.                         if (itemHit == 3) break;
  382.                     }
  383.                     if ((*frHndl)->doc.twoPlayer) SetOpponentType(frHndl, kOnePlayer);
  384.                     if (!(AppReadDocument(frHndl, gameFileType))) {
  385.                         arrangeBoard = (*frHndl)->doc.arrangeBoard;
  386.                         if (arrangeBoard)
  387.                             if (CTETargetInfo(&teHndl, &rct) == window)
  388.                                 CTEActivate(false, teHndl);
  389.                         oldPort = SetFilePort(frHndl);
  390.                         rct = window->portRect;
  391.                         EraseRect(&rct);
  392.                         ImageDocument(frHndl, false);
  393.                         if (!arrangeBoard) AdjustGameSlider(frHndl);
  394.                         UpdateGameStatus(frHndl);
  395.                         DrawTime(frHndl);
  396.                         SetPort(oldPort);
  397.                         if (!arrangeBoard) CTEWindActivate(window, true);
  398.                     }
  399.                     break;
  400.                 case iPageSetup:
  401.                     DoSetCursor(&qd.arrow);
  402.                     PresentStyleDialog(frHndl);
  403.                     break;
  404.                 case iPrint:
  405.                     DoSetCursor(&qd.arrow);
  406.                     err = noErr;
  407.                     if (!(*frHndl)->doc.printRecValid)
  408.                         err = PresentStyleDialog(frHndl);
  409.                     if (!err) {
  410.                         err = AppPrintDocument(frHndl, true, true);
  411.                         AppPrintDocument(nil, false, false);
  412.                     }
  413.                     if ((err) && (err != userCanceledErr))
  414.                         Alert(rErrorAlert, gAlertFilterUPP);
  415.                     break;
  416.                 case iQuit:
  417.                     gQuitApplication = CloseAllWindows();
  418.                     break;
  419.             }
  420.             break;
  421.  
  422.         case mEdit:            /* Call SystemEdit for DA editing & MultiFinder. */
  423.             if (IsAppWindow(window)) {
  424.                 switch (menuItem) {
  425.                     case iUndo:
  426.                         CTEUndo();
  427.                         break;
  428.                     case iCut:
  429.                     case iCopy:
  430.                     case iPaste:
  431.                     case iClear:
  432.                         CTEClipboard(menuItem - iCut + 2);
  433.                         if (menuItem != iCopy) (*frHndl)->fileState.docDirty = true;
  434.                         break;
  435.                     case iSelectAll:
  436.                         if (CTETargetInfo(&teHndl, &rct) == window) CTESetSelect(0, 32000, teHndl);
  437.                         break;
  438.                 }
  439.             }
  440.             else SystemEdit(menuItem - 1);
  441.             break;
  442.  
  443.         case mGame:
  444.             switch (menuItem) {
  445.                 case iConfigureGame:
  446.                     DoSetCursor(&qd.arrow);
  447.                     DoConfigureGame(frHndl);
  448.                     break;
  449.                 case iInvertBoard:
  450.                     (*frHndl)->doc.invertBoard ^= 1;
  451.                     if (!(*frHndl)->doc.twoPlayer) {
  452.                         if ((*frHndl)->doc.compMovesWhite + (*frHndl)->doc.compMovesBlack == 1) {
  453.                             if ((*frHndl)->doc.compMovesWhite == (*frHndl)->doc.myColor) {
  454.                                 (*frHndl)->doc.compMovesWhite ^= true;
  455.                                 (*frHndl)->doc.compMovesBlack ^= true;
  456.                                 (*frHndl)->doc.myColor        ^= true;
  457.                             }
  458.                         }
  459.                     }
  460.                     SetPort(window);
  461.                     ImageDocument(frHndl, true);
  462.                     DrawTime(frHndl);
  463.                     break;
  464.                 case iArrangeBoard:
  465.                 case iPlayOnePlayer:
  466.                 case iPlayTwoPlayer:
  467.                 case iFindTwoPlayer:
  468.                     DoSetCursor(&qd.arrow);
  469.                     if ((menuItem == iArrangeBoard) && ((*frHndl)->doc.numGameMoves)) {
  470.                         dlg = GetCenteredDialog(rArrangeWarning, nil, FrontWindow(), (WindowPtr)-1L);
  471.                         if (dlg) {
  472.                             OutlineDialogItem(dlg, 1);
  473.                             ModalDialog(gKeyEquivFilterUPP, &itemHit);
  474.                             DisposeDialog(dlg);
  475.                             if (itemHit == 3) break;
  476.                         }
  477.                     }
  478.                     nbpType = nil;
  479.                     if (menuItem == iFindTwoPlayer) {
  480.                         menuItem = iPlayTwoPlayer;
  481.                         nbpType = "\pKibitz";
  482.                     }
  483.                     if (menuItem == iPlayTwoPlayer) {
  484.                         if (!(*frHndl)->doc.twoPlayer) SendGame(frHndl, kIsMove, nbpType);
  485.                     }
  486.                     else SetOpponentType(frHndl, menuItem - iPlayOnePlayer + kOnePlayer);
  487.                     break;
  488.                 case iGoToMove:
  489.                     DoGoToMove(frHndl);
  490.                     break;
  491.                 case iAlgOut:
  492.                     DoSetCursor(*GetCursor(watchCursor));
  493.                     MovesToOutBox(frHndl, event);
  494.                     break;
  495.                 case iAlgIn:
  496.                     DoSetCursor(*GetCursor(watchCursor));
  497.                     teHndl = (*frHndl)->doc.message[kMessageOut];
  498.                     MovesFromText(frHndl, (*teHndl)->hText, (*teHndl)->teLength,
  499.                                   (*teHndl)->selStart, (*teHndl)->selEnd, false);
  500.                     break;
  501.             }
  502.             break;
  503.  
  504.     }
  505.  
  506.     HiliteMenu(0);        /* Unhighlight what MenuSelect (or MenuKey) hilited. */
  507. }
  508.  
  509.  
  510.  
  511.